let Vue

class VueRouter {
  // 构造函数
  constructor(options) {
    this.$options = options

    // 创建一个路由path和route映射
    this.routeMap = {}

    // 将来当前路径current需要响应
    // 利用vue响应式原理可以做到这一点
    this.app = new Vue({
      data: {
        current: '/'
      }
    })
  }

  init() {
    // 绑定浏览器事件
    this.bindEvents()

    // 解析路由配置
    this.createRouteMap(this.$options)

    // 创建router-link 和 router-view
    this.initComponent()
  }

  bindEvents() {
    window.addEventListener('hashchange', this.onHashChange.bind(this))
    window.addEventListener('load', this.onHashChange.bind(this))
  }

  onHashChange() {
    // http://localhost/#/home
    this.app.current = window.location.hash.slice(1)
  }

  createRouteMap(options) {
    options.routes.forEach(item => {
      // '/home': {path: '/home', component: Home}

      this.routeMap[item.path] = item
    })
  }

  initComponent() {
    // 声明两个全局组件
    Vue.compnent('router-link', {
      props: {
        to: String
      },
      render(h) {
        // 目标是： <a :href="to">
        return h(
          'a',
          {
            // 原生属性
            attrs: {
              href: '#' + this.to
            }
          },
          this.$slots.default
        )

        // JSX
        // return <a href={this.to}>{this.$slots.default}</a>
      }
    })

    Vue.compnent('router-view', {
      // 箭头函数能保留this指向
      // 这里this指向 vueRouter实例
      render: (h) => {
        const Comp = this.routeMap[this.app.current].component
        return h(Comp)
      }
    })
  }
}

// 把VueRouter变为插件
VueRouter.install = function(_Vue) {
  Vue = _Vue // 这里保存上面使用

  // 混入任务-扩展Vue
  Vue.mixin({
    beforeCreate() {
      // 这里的代码将来会在外面初始化的时候被调用
      // 这样就实现了vue的扩展
      // this Vue的组件实例
      // 但是这里只希望跟组件执行一次

      if (this.$options.router) {
        Vue.prototype.$router = this.$options.router
        this.$options.router.init()
      }
    }
  })
}
